package se.mushroomwars.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

import se.mushroomwars.gameplay.Player;
import se.mushroomwars.gameplay.Players;
import se.mushroomwars.network.protocol.Protocol;

public class ServerInterface implements DataHandleListener {

	final Runnable thread;
	private Server server;
	private Players players;
	final Thread t1;

	public ServerInterface() {
		players = new Players();
		thread = new Server(50034);
		server = (Server) thread;
		// add ServerInterface to the listener-list
		server.addListener(this);
		// init and start the server-thread
		t1 = new Thread(thread, "server");
		t1.start();
	}

	public static void main(String argv[]) throws IOException {

		final ServerInterface network = new ServerInterface();
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

		while (true) {
			System.out.print("God: ");
			network.broadcast("God: " + in.readLine(), Protocol.LOBBY_MESSAGE);
		}
	}

	public boolean send(Player player, Object data, int packageID) {
		synchronized (this) {
			return server.send(player.getSocket(), data, packageID);
		}
	}

	public void broadcast(Object data, int packageID) {
		synchronized (players) {
			for (Iterator<Player> it = players.iterator(); it.hasNext();)
				send(it.next(), data, packageID);
		}
	}

	public void broadcastAllExceptOne(Player theOne, Object data, int packageID) {
		synchronized (players) {
			Iterator<Player> itr = players.iterator();
			while (itr.hasNext()) {
				if (!(itr.next().getSocket() == theOne.getSocket()))
					send(itr.next(), data, packageID);
			}
		}
	}
	
	public void disconnectClient(Player player) {
		if (player != null)
			server.disconnectClient(player.getSocket());
	}

	@Override
	public void notifyPlayerConnected(SocketChannel socket, int playerID) {
		Player p = new Player(socket, playerID);
		players.add(p);
		// check & set admin
		players.setAdmin();
		//send a list of the connected players name(showed in the clients lobby)
		server.send(socket, players.getLobby(), Protocol.LOBBY);
	}

	public void notifyPlayerDisconnected(SocketChannel socket) {
		Player player = players.find(socket);
		assert player != null;
		System.out.println("Player: " + player.getNickName() + " Disconnected");
		players.remove(player);
		// select a new admin
		players.setAdmin();
		
		//tell all clients that a user left the game
		broadcast(new Integer(player.getID()), Protocol.PLAYER_DISCONNECTED);
	}

	public void notifyDataToHandle(SocketChannel socket, Object dataPackage,
			int packageID) {
		Player player = players.find(socket);
		assert player != null;

		// check what package we received
		switch (packageID) {
		case Protocol.BAD_PACKAGE:
			break;

		case Protocol.LOGIN: {
			String data = (String) dataPackage;
			String res = "Player: " + player.getNickName()
					+ " changed name to: " + data;
			broadcast(res, Protocol.LOBBY_MESSAGE);
			System.out.println(res);
			player.setNickName(data);
			break;
		}

		case Protocol.KICK_PLAYER: {
			String data = (String) dataPackage;
			Player p = players.find(data);

			if (player.isAdmin()) {
				if (p != null) {
					String res = "[Server]: Player: " + p.getNickName()
							+ " was kicked";
					disconnectClient(players.find(data));
					broadcast(res, Protocol.LOBBY_MESSAGE);
				} else
					send(player,
							"[Server]: Player: \"" + data + "\" not found",
							Protocol.LOBBY_MESSAGE);
			}
			break;
		}

			// player wrote something
		case Protocol.LOBBY_MESSAGE: {
			String data = (String) dataPackage;

			System.out.println(player.getNickName() + ": " + data);
			broadcast(player.getNickName() + ": " + data,
					Protocol.LOBBY_MESSAGE);
			break;
		}

		default:
			send(player, "Unknown package received. PackageID: " + packageID,
					Protocol.LOBBY_MESSAGE);
			System.out.println("Unknown package received. PackageID: "
					+ packageID + " sent by: " + player.getNickName() + ")");
		}
	}
}